<?php

/**
 * User profile form decorator
 *
 */
class Application_Form_NodeDecorator extends Zend_Form_Decorator_Abstract 
{
    protected $_elem;
    protected $_input;
    protected $_textarea;
    protected $_date;
    protected $_label;
    protected $_message;
    protected $_error;
    
    protected $_locale;
    
    public function __construct($options = null)
    {
        $this->_elem='<div class="node-form-item">%s</div>';
        $this->_label='<div class="field-label"><label for="%s">%s</label></div>';
        $this->_input='<div class="field"><input type="%s" name="%s" id="%s" value="%s" /></div>';
        $this->_textarea='<div class="field"><textarea name="%s" id="%s" rows="10" cols="40">%s</textarea></div>';
        $this->_textarea_full='<div class="field"><textarea class="wysiwyg" name="%s" id="%s" rows="20" cols="40">%s</textarea></div>';
        $this->_message='<div class="field-message">%s</div>';
        $this->_error='<div class="error">%s</div>';
        
        $this->_locale=Zend_Registry::get('locale');
    }
    
    /**
     * Decorator render interface function
     *
     * @param string $content
     * @return string
     */
    public function render($content)
    {
        $element=$this->getElement();
        
        $type=$this->_getFieldTypeById($element->getType());
        
        $label=$this->_locale->_($element->getLabel());
        $id=$element->getId();
        $name=$element->getFullyQualifiedName();
        $value=$this->_locale->_($element->getValue());
        $message='';
        
        $messages=$element->getMessages();
        if (!empty($messages))
        {
            $message.='<ul>';
            foreach ($messages as $mess_code=>$mess_text)
            {
                $message.='<li>'.$this->_locale->_($this->_getMessageById($mess_code)).'</li>';
            }
            $message.='</ul>';
        }
        
        if (!empty($message))
        {
            $message=$this->_wrap_error($message);
        }
        
        if ($type=='date')  return $this->_wrap_date($id,$label,$message,$content);
        if ($type=='checkbox')  return $this->_wrap_checkbox($id,$label,$message,$content);
        if ($type=='select') return $this->_wrap_select($id,$label,$message,$content);
        
        return $this->_wrap_content($id,$label,$type,$name,$value,$message);
    }

    /**
     * Form element wrapper
     *
     * @param string $content
     * @return string
     */
    protected function _wrap_element($content)
    {
        return sprintf($this->_elem,$content);
    }
    
    /**
     * Form element label wrapper
     *
     * @param string $id
     * @param string $label
     * @return string
     */
    protected function _wrap_label($id,$label)
    {
        return sprintf($this->_label,$id,$label);
    }
    
    /**
     * Form input element wrapper
     *
     * @param string $type
     * @param string $name
     * @param string $id
     * @param string $value
     * @return string
     */
    protected function _wrap_input($type,$name,$id,$value)
    {
        return sprintf($this->_input,$type,$name,$id,$value);
    }
    
    /**
     * Form textarea element wrapper
     *
     * @param string $name
     * @param string $id
     * @param string $value
     * @return string
     */
    protected function _wrap_textarea($name,$id,$value)
    {
        if ($id=='full_text') return sprintf($this->_textarea_full,$name,$id,$value);
        
        return sprintf($this->_textarea,$name,$id,$value);
    }
    
    /**
     * Form element message wrapper
     *
     * @param string $message
     * @return string
     */
    protected function _wrap_message($message)
    {
        return sprintf($this->_message,$message);
    }
    
    /**
     * Error message wrapper
     *
     * @param string $error
     * @return string
     */
    protected function _wrap_error($error)
    {
        return sprintf($this->_error,$error);
    }
    
    /**
     * Form item wrapper
     *
     * @param string $id
     * @param string $label
     * @param string $type
     * @param string $name
     * @param string $value
     * @param string $message
     * @return string
     */
    protected function _wrap_content($id,$label,$type,$name,$value,$message)
    {
        $label=$this->_wrap_label($id,$label);
        
        if ($type=='textarea')
        {
            $elem=$this->_wrap_textarea($name,$id,$value);
        } else 
        {
            $elem=$this->_wrap_input($type,$name,$id,$value);
        }
        
        $message=$this->_wrap_message($message);
        
        return $this->_wrap_element($label.$elem.$message);
    }
    
    /**
     * Date wrapper
     *
     * @param string $id
     * @param string $label
     * @param string $message
     * @param string $date
     * @return string
     */
    protected function _wrap_date($id,$label,$message,$date)
    {
        $content='';

        $label=$this->_wrap_label($id,$label);
        $message=$this->_wrap_message($message);
        
        return $this->_wrap_element($label.$date.$message);
    }
    
    /**
     * Checkbox wrapper
     *
     * @param string $id
     * @param string $label
     * @param string $message
     * @param string $checkbox
     * @return string
     */
    protected function _wrap_checkbox($id,$label,$message,$checkbox)
    {
        $content='';

        $label=$this->_wrap_label($id,$label);
        $message=$this->_wrap_message($message);

        if (preg_match_all('/(<input.+?>)/s',$checkbox,$matches))
        {
            foreach ($matches[1] as $m)
            {
                $content.=$m;
            }
        }
        
        return $this->_wrap_element($label.$content.$message);
    }
    
    /**
     * Select wrapper
     *
     * @param string $id
     * @param string $label
     * @param string $message
     * @param string $select
     * @return string
     */
    protected function _wrap_select($id,$label,$message,$select)
    {
        $content='';

        $label=$this->_wrap_label($id,$label);
        $message=$this->_wrap_message($message);
        
        if (preg_match('/(<select.+?\/select>)/s',$select,$matches))
        {
            $content=$matches[1];
        }
        
        return $this->_wrap_element($label.$content.$message);
    }
    
    /**
     * Returns form field types
     *
     * @return array
     */
    protected function _getFieldTypes()
    {
        return array(
            'Zend_Form_Element_Text' => 'text',
            'Zend_Form_Element_Password' => 'password',
            'Zend_Form_Element_Submit' => 'submit',
            'Zend_Form_Element_Hash' => 'hidden',
            'Zend_Form_Element_Checkbox' => 'checkbox',
            'Zend_Form_Element_Select' => 'select',
            'Zend_Form_Element_Textarea' => 'textarea',
            'ZendX_Form_Element_DatePicker' => 'date'
        );
    }
    
    /**
     * Returns form default field type
     * Should never be used
     *
     * @return string
     */
    protected function _getDefaultFieldType()
    {
        $types=array_values($this->_getFieldTypes());
        
        return $types[0];
    }
    
    /**
     * Returns form element type
     *
     * @param string $id
     * @return string
     */
    protected function _getFieldTypeById($id)
    {
        $types=$this->_getFieldTypes();
        
        if (array_key_exists($id,$types))
        {
            return $types[$id];
        } else 
        {
            return $this->_getDefaultFieldType();
        }
    }
    
    /**
     * Returns an array with form messages
     *
     * @return array
     */
    protected function _getMessages()
    {
        return array(
                'isEmpty' => 'This field must be filled',
                'stringLengthTooShort' => 'Given value is too short',
                'stringLengthTooLong' => 'Given value is too long',
                'dateFalseFormat' => 'Invalid date format',
                'invalidURL' => 'Invalid URL',
                'notAlnum' => 'This field should contain only alphanumeric characters',
                'notSame' => 'Value do not match',
                'missingToken' => 'Hash not received or expired'
        );
    }
    
    /**
     * Returns default error message;
     * Should never be used
     *
     * @return string
     */
    protected function _getDefaultMessage()
    {
        return 'Invalid data';
    }
    
    /**
     * Returns message text by ID
     *
     * @param string $id
     * @return string
     */
    protected function _getMessageById($id)
    {
        $messages=$this->_getMessages();
        
        if (array_key_exists($id,$messages))
        {
            return $messages[$id];
        } else 
        {
            return $this->_getDefaultMessage();
        }
    }
}